#region Imports

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;

using BO = PHSRAG.Insight21.BusinessObjects;
using DataAccess = PHSRAG.Utility.DataAccess;
using ICachePolicy = PHSRAG.Insight21.Policy.ICachePolicy;

#endregion

namespace PHSRAG.Insight21.Humans
{
	/// <summary>
	/// Represents the people staffed to a study.  
	/// </summary>
	public class StudyStaff : BO.BusinessObject
	{

		#region Constants

		private const string StudyStaffKey = "studyStaffKey_0B2B28E6-770B-4dc5-BFE1-C854A430E9DF";
		private const string StudyStaffTableName = "studyStaff";
		#endregion

		#region Public Properties

		/// <summary>
		/// Get the key to be used in all caching operations for this instance of the object.
		/// </summary>
		public static string CacheKey	{ get { return StudyStaffKey; } }

		/// <summary>
		/// Returns the number of people staffed to the study
		/// </summary>
		public int Count
		{
			get
			{ 
				return DataContainer.Tables[StudyStaffTableName].Rows.Count;
			}
		}

		#endregion

        #region Constructor
		/// <summary>
		/// Initializes the base class with the specified cache policy.
		/// </summary>
		/// <param name="cachePolicy"></param>
		public StudyStaff(ICachePolicy cachePolicy) : base(cachePolicy)
		{
		}

		#endregion

		#region BusinessObject Methods

		/// <summary>
		/// Cache the current instance using the prevalent cache policy.
		/// </summary>
		public override void Cache()
		{
			CachePolicy.Cache(CacheKey, this);
		}

		/// <summary>
		/// Remove the current instance from the cache using the prevalent cache policy.
		/// </summary>
		public override void UnCache()
		{
			CachePolicy.UnCache(CacheKey);
		}

		/// <summary>
		/// Load the current instance with summary study staff person data for the current protocol or protocol process
		/// </summary>
		/// <param name="connectionString">Database connection string</param>
		/// <param name="args"></param>
		public override void Load(string connectionString, params object[] args)
		{
			if (args.Length != 2)
				throw new Exception("StudyStaff load requires a protocol number or a process id");

			try
			{
				DataContainer = DataAccess.GetDataSet(
					connectionString,
					"GetStudyStaff",
					DataAccess.BuildSqlParameterArray("@protocolId", SqlDbType.Int, args[0],
							"@protocolProcessId", SqlDbType.Int, args[1]));
				DataContainer.Tables[0].TableName = StudyStaffTableName;
			}
			catch(Exception e)
			{
				Utility.ExceptionReport.WriteToEventLog("StudyStaff Load", e, true, Utility.ExceptionReport.ReportType.Error);
				throw new Exception("StudyStaff Load failed", e);
			}
		}

		#endregion

		#region Public Methods

		/// <summary>
		/// Returns a list of people staffed to the study.  Using the dataContainer as the source data, 
		/// a StaffPerson object is instantiated per row and added to an ArrayList
		/// </summary>
		/// <returns>ArrayList of StaffPerson objects</returns>
		public ArrayList GetStudyStaffList()
		{
			DataTable table = DataContainer.Tables[StudyStaffTableName];
			int staffCount = table.Rows.Count;
			ArrayList studyStaff = new ArrayList(staffCount);

			for(int i = 0; i < staffCount; ++i)
				studyStaff.Add(new StaffPerson(CachePolicy, table.Rows[i]));

			return studyStaff;
		}


		/// <summary>
		/// Returns a distinct list of people staffed to the study with their roles grouped. 
		/// </summary>
		/// <returns>Hashtable of StaffPerson objects</returns>
		public Hashtable GetDistinctStaffIdsWithGroupedRoles()
		{
			DataTable table = DataContainer.Tables[StudyStaffTableName];
			int staffCount = table.Rows.Count;
			Hashtable groupedRoles = new Hashtable();

			for(int i = 0; i < staffCount; ++i)
			{
				object admPersonId = table.Rows[i]["AdmPersonId"];
				if (!groupedRoles.ContainsKey(admPersonId))
				{
					groupedRoles.Add(admPersonId, table.Rows[i]["Role"].ToString().Trim());
				}
				else
				{
					groupedRoles[admPersonId] = groupedRoles[admPersonId].ToString() + "|" + table.Rows[i]["Role"].ToString().Trim();
				}
			}

			return groupedRoles;
		}

		#endregion
		
		/// <summary>
		/// Returns a list of people within the Partners' domain
		/// </summary>
		/// <param name="connectionString">string containing info to connect to the database</param>
		/// <param name="protocolId">id of the protocol to query</param>
		/// <returns>records of internal people</returns>
		public static DataSet GetPotentialStaff(string connectionString, int protocolId, int protocolProcessId,
			string lastName, string firstName, string username, int orgId)
		{	
			try 
			{

				return DataAccess.GetDataSet(
					connectionString,
					"GetPotentialStaff", 
					Utility.DataAccess.BuildSqlParameterArray(
					"@protocolId", SqlDbType.Int, protocolId,
					"@protocolProcessId", SqlDbType.Int, protocolProcessId,
					"@lastName", SqlDbType.VarChar, (lastName == string.Empty) ? (object)DBNull.Value : (object)lastName,
					"@firstName", SqlDbType.VarChar, (firstName == string.Empty) ? (object)DBNull.Value : (object)firstName,
					"@userName", SqlDbType.VarChar, (username == string.Empty) ? (object)DBNull.Value : (object)username,
					"@organizationId", SqlDbType.Int, orgId));
			}
			catch (Exception ex)
			{
				throw new Exception ("Retrieving potential staff failed", ex);
			}
		}

		/// <summary>
		/// Returns a list of external people that have previously
		/// been staffed to a protocol
		/// </summary>
		/// <param name="connectionString">string containing info to connect to the database</param>
		/// <param name="protocolId">id of the protocol to query</param>
		/// <returns>records of previously staffed external people</returns>
		public static DataSet GetExternalStaff(string connectionString, int protocolId, int protocolProcessId,
			string lastName, string firstName)
		{	
			try 
			{
				return DataAccess.GetDataSet(
					connectionString,
					"GetExternalStaff", 
					Utility.DataAccess.BuildSqlParameterArray(
					"@protocolId", SqlDbType.Int, protocolId,
					"@protocolProcessId", SqlDbType.Int, protocolProcessId,
					"@lastName", SqlDbType.VarChar, (lastName == string.Empty) ? (object)DBNull.Value : (object)lastName,
					"@firstName", SqlDbType.VarChar, (firstName == string.Empty) ? (object)DBNull.Value : (object)firstName));
			}
			catch (Exception ex)
			{
				throw new Exception ("Retrieving external staff failed", ex);
			}
		}


		/// <summary>
		/// Returns a list of roles for staffing a Humans study
		/// </summary>
		/// <param name="connectionString">string containing info to connect to the database</param>
		/// <returns>a dataTable of Name/Id pairs</returns>
		public static DataTable GetHumansStudyRoles(string connectionString)
		{
			try 
			{
				return DataAccess.GetDataSet(connectionString,"GetStudyRoles").Tables[0];
			}
			catch (Exception ex)
			{
				throw new Exception ("Retrieving Humans study roles failed", ex);
			}
		}


        /// <summary>
        /// Returns a list of roles for staffing an Animals study
        /// </summary>
        /// <param name="connectionString">string containing info to connect to the database</param>
        /// <returns>a dataTable of Name/Id pairs</returns>
        public static DataTable GetAnimalsStudyRoles(string connectionString)
        {
            try
            {
                return DataAccess.GetDataSet(connectionString, "GetAnimalsStudyRoles").Tables[0];
            }
            catch (Exception ex)
            {
                throw new Exception("Retrieving Animals study roles failed", ex);
            }
        }
	}
}
